﻿using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace JCW.Common
{
    /// <summary>
    /// 加密解密帮助类
    /// </summary>
    public static class CryptoHelper
    {
        #region 默认密钥
        /// <summary>
        /// TripleDES默认密钥
        /// </summary>
        private const string TRIPLE_DES_KEY = "顀ぽ頿‡䱷を顠み䦷䦆顢䦆";
        /// <summary>
        /// DES默认密钥
        /// </summary>
        private const string DES_KEY = "䦆頿䱷顠";
        #endregion


        #region TripleDES加密
        /// <summary>
        /// TripleDES加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <param name="key">密钥</param>
        /// <returns>加密后字符串</returns>
        public static string TripleDESEncrypt(string data, string key)
        {
            byte[] bt = (new System.Text.UnicodeEncoding()).GetBytes(data);
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(key, null);
            byte[] rgbkey = pdb.GetBytes(24);
            byte[] rgbiv = pdb.GetBytes(8);
            MemoryStream ms = new MemoryStream();
            TripleDESCryptoServiceProvider tdesc = new TripleDESCryptoServiceProvider();
            CryptoStream cs = new CryptoStream(ms, tdesc.CreateEncryptor(rgbkey, rgbiv), CryptoStreamMode.Write);
            cs.Write(bt, 0, bt.Length);
            cs.FlushFinalBlock();
            return Convert.ToBase64String(ms.ToArray());
        }
        #endregion

        #region TripleDES解密
        /// <summary>
        /// TripleDES解密
        /// </summary>
        /// <param name="str">被加密的字符串</param>
        /// <param name="key">密钥</param>
        /// <returns>解密后字符串</returns>
        public static string TripleDESDecrypt(string data, string key)
        {

            byte[] bt = Convert.FromBase64String(data);
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(key, null);
            byte[] rgbkey = pdb.GetBytes(24);
            byte[] rgbiv = pdb.GetBytes(8);
            MemoryStream ms = new MemoryStream();
            TripleDESCryptoServiceProvider tdesc = new TripleDESCryptoServiceProvider();
            CryptoStream cs = new CryptoStream(ms, tdesc.CreateDecryptor(rgbkey, rgbiv), CryptoStreamMode.Write);
            cs.Write(bt, 0, bt.Length);
            cs.FlushFinalBlock();
            return (new System.Text.UnicodeEncoding()).GetString(ms.ToArray());

        }
        #endregion

        #region TripleDES加密
        /// <summary>
        /// TripleDES加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <returns>加密后字符串</returns>
        public static string TripleDESEncrypt(string data)
        {
            return TripleDESEncrypt(data, TRIPLE_DES_KEY);
        }
        #endregion

        #region TripleDES解密
        /// <summary>
        /// TripleDES解密
        /// </summary>
        /// <param name="data">被加密的字符串</param>
        /// <returns>解密后字符串</returns>
        public static string TripleDESDecrypt(string data)
        {
            return TripleDESDecrypt(data, TRIPLE_DES_KEY);
        }
        #endregion


        #region DES加密
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <param name="key">密钥</param>
        /// <returns>加密后字符串</returns>
        public static string DESEncrypt(string data, string key)
        {
            //有效验证
            if (key.Length != 4)
                throw new ArgumentOutOfRangeException("key", "参数密钥的长度必须是4，传入的密钥长度不合法");

            //定义DES加密服务提供类
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            //加密字符串转换为byte数组
            byte[] inputByte = UnicodeEncoding.Unicode.GetBytes(data);
            //加密密匙转化为byte数组
            byte[] deskey = UnicodeEncoding.Unicode.GetBytes(key);

            des.Key = deskey;
            des.IV = deskey;
            //创建其支持存储区为内存的流
            MemoryStream ms = new MemoryStream();
            //定义将数据流链接到加密转换的流
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);

            cs.Write(inputByte, 0, inputByte.Length);
            cs.FlushFinalBlock();
            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                //向可变字符串追加转换成十六进制数字符串的加密后byte数组。
                ret.AppendFormat("{0:X2}", b);
            }
            return ret.ToString();
        }
        #endregion

        #region DES解密
        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="data">被解密的加密字符串</param>
        /// <param name="key">密钥</param>
        /// <returns>解密后字符串</returns>
        public static string DESDecrypt(string data, string key)
        {
            //有效验证
            if (key.Length != 4)
                throw new ArgumentOutOfRangeException("key", "参数密钥的长度必须是4，传入的密钥长度不合法");

            //定义DES加密解密服务提供类
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            //加密密匙转化为byte数组
            byte[] deskey = UnicodeEncoding.Unicode.GetBytes(key);
            des.Key = deskey;
            des.IV = deskey;
            //将被解密的字符串每两个字符以十六进制解析为byte类型，组成byte数组
            int length = (data.Length / 2);
            byte[] inputByte = new byte[length];
            for (int index = 0; index < length; index++)
            {
                string substring = data.Substring(index * 2, 2);
                inputByte[index] = Convert.ToByte(substring, 16);
            }
            //创建其支持存储区为内存的流
            MemoryStream ms = new MemoryStream();
            //定义将数据流链接到加密转换的流
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(inputByte, 0, inputByte.Length);
            cs.FlushFinalBlock();

            return UnicodeEncoding.Unicode.GetString((ms.ToArray()));
        }
        #endregion

        #region DES加密
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <returns>加密后字符串</returns>
        public static string DESEncrypt(string data)
        {
            return DESEncrypt(data, DES_KEY);
        }
        #endregion

        #region DES解密
        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="data">被解密的加密字符串</param>
        /// <returns>解密后字符串</returns>
        public static string DESDecrypt(string data)
        {
            return DESDecrypt(data, DES_KEY);
        }
        #endregion


        #region 标准MD5加密
        /// <summary>
        /// 标准MD5加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <param name="addKey">附加字符串</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>加密后字符串</returns>
        public static string MD5Encrypt(string data, string addKey, Encoding encoding)
        {
            if (addKey.Length > 0)
            {
                data = data + addKey;
            }

            MD5 MD5 = new MD5CryptoServiceProvider();
            byte[] datSource = encoding.GetBytes(data);
            byte[] newSource = MD5.ComputeHash(datSource);
            string byte2String = null;
            for (int i = 0; i < newSource.Length; i++)
            {
                string thisByte = newSource[i].ToString("x");
                if (thisByte.Length == 1) thisByte = "0" + thisByte;
                byte2String += thisByte;
            }
            return byte2String;
        }
        #endregion

        #region 标准MD5加密
        /// <summary>
        /// 标准MD5加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>加密后字符串</returns>
        public static string MD5Encrypt(string data, string encoding)
        {
            return MD5Encrypt(data, string.Empty, Encoding.GetEncoding(encoding));
        }
        #endregion

        #region 标准MD5加密
        /// <summary>
        /// 标准MD5加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <returns>加密后字符串</returns>
        public static string MD5Encrypt(string data)
        {
            return MD5Encrypt(data, string.Empty, Encoding.Default);
        }
        #endregion

        #region SHA1加密
        /// <summary>
        /// SHA1加密，等效于 PHP 的 SHA1() 代码
        /// </summary>
        /// <param name="source">被加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string SHA1Encrypt(string source)
        {
            byte[] temp1 = Encoding.UTF8.GetBytes(source);

            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
            byte[] temp2 = sha.ComputeHash(temp1);
            sha.Clear();

            //注意，不能用这个
            //string output = Convert.ToBase64String(temp2); 

            string output = BitConverter.ToString(temp2);
            output = output.Replace("-", string.Empty);
            output = output.ToLower();
            return output;
        }
        #endregion
    }
}
